import uuid
from datetime import datetime, time
from pprint import pprint

from django.db import models, transaction
from django.db.models import F

from jqexception.jqexecption import NullErr, ValueErr
from warehouse.models import JuqiGood
from wxcloudrun.models import BaseModel

from enum import Enum, auto, unique


# Create your models here.
# user models
@unique
class UserState(models.IntegerChoices):
    normal = 0  # 正常
    block = 1  # 拉黑


class Users(BaseModel):
    # base info
    openid = models.CharField(max_length=40, unique=True)

    nickname = models.CharField(max_length=30, unique=True)
    head_url = models.CharField(
        max_length=255,
    )
    # 等级
    lv = models.IntegerField(default=1)
    # real name auth
    realname = models.CharField(max_length=30, blank=True)
    telephone = models.CharField(max_length=30, blank=True)
    idcard_num = models.CharField(max_length=30, blank=True)

    # 是否实名
    is_real = models.BooleanField(default=False)

    # 邀请人uuid
    inviter_uuid = models.UUIDField(null=True)

    # 是否代理
    is_daili = models.BooleanField(default=False)

    # 状态
    state = models.PositiveSmallIntegerField(
        choices=UserState.choices, default=UserState.normal
    )
    # wealth
    # 实际充值的钱，禁止后台管理员充值， 修改，支持退款
    stored_money = models.IntegerField(default=0)
    # 回收赏品，以及提现需要消耗的， 提现只能在后台管理平台操作
    hunjing = models.IntegerField(default=0)
    # 奖励给用户的， 1：1 vs hunjing，不能提现，前端显示，* 100， 让人看起来很爽
    score = models.IntegerField(default=0)

    package_amount = models.IntegerField(default=0, verbose_name="赏柜价值")  # 赏柜的价值
    delivery_amount = models.IntegerField(default=0, verbose_name="发货价值")  # 发货的价值
    # if true, ui will show help step, else not
    need_help = models.BooleanField(
        default=True,
    )

    class Meta:
        db_table = "Users"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["openid"]),
            models.Index(fields=["telephone"]),
            models.Index(fields=["realname"]),
            models.Index(fields=["idcard_num"]),
            models.Index(fields=["is_real"]),
            models.Index(fields=["is_daili"]),
            models.Index(fields=["inviter_uuid"]),
            models.Index(fields=["state"]),
        ]


@unique
class OrderState(Enum):
    # 待支付, 从 1 开始
    wait = auto()
    # 支付成功
    success = auto()
    # 已经退款
    refund = auto()


@unique
class UserRechargeType(models.IntegerChoices):  # 充值类型
    weixin = 1  # 微信
    admin = 2  # 管理员


def hex_uuid():
    return uuid.uuid4().hex


class UserRechargeOrder(BaseModel):
    # base info
    # 充值订单
    openid = models.CharField(max_length=40)
    out_trade_no = models.CharField(default=hex_uuid, max_length=32, unique=True)
    total_fee = models.PositiveIntegerField()
    # 参考 OrderState
    state = models.IntegerField(default=OrderState.wait.value)

    # 充值类型
    recharge_type = models.PositiveIntegerField(
        choices=UserRechargeType.choices, default=UserRechargeType.weixin
    )

    # 如果是管理员充值记录管理员uuid
    admin_uuid = models.UUIDField(null=True, default=None)

    class Meta:
        db_table = "UserRechargeOrder"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["openid"]),
            models.Index(fields=["state"]),
            models.Index(fields=["out_trade_no"]),
            models.Index(fields=["admin_uuid"]),
        ]
        ordering = ["-createdAt"]


class UserPackage(BaseModel):
    # base info
    # 记录用户财富变更
    user_uuid = models.UUIDField()

    # wealth
    good_uuid = models.UUIDField()
    count = models.PositiveIntegerField(default=1)

    class Meta:
        db_table = "UserPackage"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
            models.Index(fields=["good_uuid"]),
        ]


class UserPackageRecord(BaseModel):
    # base info
    # 记录用户财富变更
    user_uuid = models.UUIDField()

    # wealth
    good_uuid = models.UUIDField()
    count = models.IntegerField()

    # detail
    detail = models.CharField(max_length=240)

    class Meta:
        db_table = "UserPackageRecord"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
        ]


class UserStoredMoneyRecord(BaseModel):
    # base info
    # 记录用户财富变更
    user_uuid = models.UUIDField()

    # wealth
    stored_money = models.IntegerField(default=0)
    old_stored_money = models.PositiveIntegerField(default=0)
    new_stored_money = models.PositiveIntegerField(default=0)

    # detail
    detail = models.CharField(max_length=240)

    class Meta:
        db_table = "UserStoredMoneyRecord"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
        ]
        ordering = ["-createdAt"]


class UserHunJingRecord(BaseModel):
    # base info
    # 记录用户财富变更
    user_uuid = models.UUIDField()

    # wealth
    hunjing = models.IntegerField(default=0)
    old_hunjing = models.PositiveIntegerField(default=0)
    new_hunjing = models.PositiveIntegerField(default=0)

    # detail
    detail = models.CharField(max_length=240)

    class Meta:
        db_table = "UserHunJingRecord"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
        ]
        ordering = ["-createdAt"]


class UserScoreRecord(BaseModel):
    # base info
    # 记录用户财富变更
    user_uuid = models.UUIDField()

    # wealth
    score = models.IntegerField(default=0)
    old_score = models.PositiveIntegerField(default=0)
    new_score = models.PositiveIntegerField(default=0)
    manager = models.CharField(max_length=200, default="")

    # detail
    detail = models.CharField(max_length=240)

    class Meta:
        db_table = "UserScoreRecord"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
        ]
        ordering = ["-createdAt"]


class UserOrder(BaseModel):
    user_uuid = models.UUIDField()
    game_uuid = models.UUIDField()
    son_uuid = models.UUIDField(null=True)
    box_num = models.IntegerField(default=0)

    orderid = models.CharField(max_length=40, verbose_name="订单号")
    game_name = models.CharField(max_length=50, verbose_name="对局名称")
    price = models.PositiveIntegerField(default=0, verbose_name="抽奖单价")
    num = models.IntegerField(default=1, verbose_name="抽奖次数")
    weixin = models.PositiveIntegerField(default=0, verbose_name="微信支付")
    money = models.PositiveIntegerField(default=0, verbose_name="余额")
    hunjing = models.PositiveIntegerField(default=0, verbose_name="魂晶")
    score = models.PositiveIntegerField(default=0, verbose_name="赏币")
    coupon = models.PositiveIntegerField(default=0, verbose_name="优惠卷")
    game_type = models.IntegerField(default=0, verbose_name="游戏类型")

    class Meta:
        db_table = "UserOrder"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
            models.Index(fields=["orderid"]),
            models.Index(fields=["game_name"]),
            models.Index(fields=["game_type"]),
            models.Index(fields=["num"]),
            models.Index(fields=["money"]),
            models.Index(fields=["hunjing"]),
        ]
        ordering = ["-createdAt"]


@unique
class UserOrderGoodsState(models.IntegerChoices):
    unhandled = 0  # 未处理
    refined = 1  # 分解
    delivery = 2  # 发货


class UserOrderGoods(BaseModel):
    """用户订单含有物品关联表"""

    order_uuid = models.UUIDField(verbose_name="订单id")
    good_uuid = models.UUIDField(verbose_name="物品id")
    state = models.PositiveIntegerField(
        choices=UserOrderGoodsState.choices,
        verbose_name="订单状态",
        default=UserOrderGoodsState.unhandled,
    )

    class Meta:
        db_table = "UserOrderGoods"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["order_uuid"]),
            models.Index(fields=["good_uuid"]),
            models.Index(fields=["state"]),
        ]
        ordering = ["-createdAt"]


def add_user_order_goods(order_uuid, goods_uuid_list):
    """
    添加物品到用户订单物品里面
    Args:
        order_uuid: 订单表uuid
        goods_uuid_list: 物品uuid列表

    Returns: 被添加的数据

    """
    if len(goods_uuid_list) <= 0:
        return

    if order_uuid is None:
        raise NullErr

    goods_list = []

    for goods_uuid in goods_uuid_list:
        goods = UserOrderGoods()
        goods.good_uuid = goods_uuid
        goods.order_uuid = order_uuid
        goods_list.append(goods)

    return UserOrderGoods.objects.bulk_create(goods_list, len(goods_list))


def refined_user_order_goods(user_uuid, goods_uuid, count):
    if user_uuid is None or goods_uuid is None or count is None or count == 0:
        raise ValueErr
    _order_uuid = (
        UserOrder.objects.filter(deleted=False)
        .filter(user_uuid=user_uuid)
        .annotate(order_uuid=F("uuid"))
        .values_list("order_uuid")
        .all()
    )

    _user_goods = JuqiGood.objects.filter(uuid=goods_uuid).first()

    _order_uuid_list = []
    for order_uuid in _order_uuid:
        _order_uuid_list.append(order_uuid[0])

    _query_set = (
        UserOrderGoods.objects.filter(deleted=False)
        .filter(order_uuid__in=_order_uuid_list)
        .filter(good_uuid=goods_uuid)
        .filter(state=UserOrderGoodsState.unhandled)
    )

    _count = _query_set.all().count()
    if _count == 0:
        return
    if _count < count:
        _query_set = _query_set.all()
    else:
        _query_set = _query_set.all()[:count]

    user_order_refined_dict = dict()

    user_order_refined_goods_list = []

    for order_goods in _query_set:
        order_goods.state = UserOrderGoodsState.refined
        user_order_refined = user_order_refined_dict.get(
            order_goods.order_uuid.__str__()
        )
        if user_order_refined is None:
            user_order_refined = UserRefinedOrder(
                order_uuid=order_goods.order_uuid, user_uuid=user_uuid
            )
            user_order_refined.save()
            user_order_refined_dict[
                order_goods.order_uuid.__str__()
            ] = user_order_refined

        user_order_refined.sale_count += 1
        user_order_refined.sale_money += _user_goods.recovery_price
        user_order_refined_goods = UserRefinedOrderGoods(
            order_refined_uuid=user_order_refined.uuid,
            order_goods_uuid=order_goods.uuid,
            good_uuid=order_goods.good_uuid,
        )
        user_order_refined_goods_list.append(user_order_refined_goods)

    UserOrderGoods.objects.bulk_update(
        _query_set, fields=["state"], batch_size=len(_query_set)
    )
    UserRefinedOrderGoods.objects.bulk_create(
        user_order_refined_goods_list,
        update_fields=["order_refined_uuid", "order_goods_uuid", "good_uuid"],
        batch_size=len(user_order_refined_goods_list),
    )
    user_order_refined_list = list(user_order_refined_dict.values())
    UserRefinedOrder.objects.bulk_update(
        user_order_refined_list,
        fields=["sale_count", "sale_money"],
        batch_size=len(user_order_refined_goods_list),
    )


class UserRefinedOrder(BaseModel):
    orderid = models.CharField(max_length=40, verbose_name="订单号")
    user_uuid = models.UUIDField(verbose_name="用户uuid")
    sale_count = models.PositiveIntegerField(default=0, verbose_name="寄售数量")
    sale_money = models.PositiveIntegerField(default=0, verbose_name="寄售金额")

    class Meta:
        db_table = "UserRefinedOrder"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["orderid"]),
            models.Index(fields=["user_uuid"]),
        ]
        ordering = ["-createdAt"]


class UserRefinedOrderGoods(BaseModel):
    order_refined_uuid = models.UUIDField(verbose_name="订单提炼记录")
    user_package_uuid = models.UUIDField(verbose_name="订单含有物品关联uuid")
    good_uuid = models.UUIDField(verbose_name="物品id")

    class Meta:
        db_table = "UserRefinedOrderGoods"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["order_refined_uuid"]),
            models.Index(fields=["user_package_uuid"]),
            models.Index(fields=["good_uuid"]),
        ]
        ordering = ["-createdAt"]


@unique
class UserPaymentType(models.IntegerChoices):
    """支付类型"""

    unpaid = 0  # 未付款
    weixin = 1  # 微信


class UserShippingInformation(BaseModel):
    """用户收货信息"""

    user_uuid = models.UUIDField(verbose_name="用户uuid")
    name = models.CharField(max_length=100, verbose_name="收货人姓名")
    phone = models.CharField(max_length=20, verbose_name="收货人手机号")
    address = models.CharField(max_length=255, verbose_name="收货地址")

    class Meta:
        db_table = "UserShippingInformation"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["user_uuid"]),
            models.Index(fields=["name"]),
        ]
        ordering = ["-createdAt"]


@unique
class UserShipmentOrderState(models.IntegerChoices):
    unshipped = 0  # 未发货
    shipped = 1  # 已发货


@unique
class UserShipmentOrderType(models.IntegerChoices):
    """用户发货订单类型"""

    chou_shang = 0


class UserShipmentOrder(BaseModel):
    """用户发货订单表"""

    order_uuid = models.UUIDField(verbose_name="用户订单uuid")
    shipping_price = models.PositiveIntegerField(default=0, verbose_name="运费")  # 单位:分
    payment_type = models.PositiveIntegerField(
        choices=UserPaymentType.choices,
        verbose_name="支付方式",
        default=UserPaymentType.unpaid,
    )
    shipping_uuid = models.UUIDField(verbose_name="收货uuid")
    order_state = models.PositiveIntegerField(
        choices=UserShipmentOrderState.choices,
        verbose_name="发货订单状态",
        default=UserShipmentOrderState.unshipped,
    )
    order_type = models.PositiveIntegerField(
        choices=UserShipmentOrderType.choices,
        verbose_name="发货订单类型",
        default=UserShipmentOrderType.chou_shang,
    )

    class Meta:
        db_table = "UserShipmentOrder"  # 数据库表名
        indexes = [
            models.Index(fields=["uuid"]),
            models.Index(fields=["deleted"]),
            models.Index(fields=["createdAt"]),
            models.Index(fields=["order_uuid"]),
            models.Index(fields=["shipping_uuid"]),
            models.Index(fields=["order_state"]),
            models.Index(fields=["order_type"]),
            models.Index(fields=["payment_type"]),
        ]
        ordering = ["-createdAt"]
